import 'dart:math';

import 'package:flutter/material.dart';
import 'package:whale/helper/utils/util.dart';
import 'package:whale/pages/im/im/index.dart';

import 'index.dart';

class ImInputController extends GetxController {
  ImInputController();
  final imCtrl = Get.find<ImController>();

  final state = ImInputState();

  /// 在 widget 内存中分配后立即调用。
  @override
  void onInit() {
    super.onInit();
    state.initialization();

    state.textCtrl.addListener(() {
      setupStatus();
    });
    state.focusNode.addListener(() {
      setupStatus();
      if (state.focusNode.hasFocus) {
        imCtrl.scrollToEnd();
      }
    });
  }

  void setupStatus() {
    if (state.textCtrl.text.isEmpty) {
      if (state.focusNode.hasFocus) {
        state.status = ImInputStatus.edit;
      } else {
        state.status = ImInputStatus.none;
      }
    } else {
      if (state.style == ImInputStyle.text) {
        state.status = ImInputStatus.inputing;
      } else {
        state.status = ImInputStatus.textInputOther;
      }
    }
    update(['send', 'add-c']);
  }

  void resignFirstResponder() {
    if (state.status == ImInputStatus.textNoInput) {
      return;
    }
    if (state.textCtrl.text.isEmpty) {
      state.status = ImInputStatus.none;
    } else {
      state.status = ImInputStatus.textNoInput;
    }

    state.style = ImInputStyle.text;
    state.focusNode.unfocus();
    update();
  }

  void actionInput() {
    if (state.style == ImInputStyle.text) {
      return;
    }
    state.style = ImInputStyle.text;
    state.status = ImInputStatus.inputing;

    update();
    reCallKeyboard();
  }

  void actionVoice() {
    if (state.style != ImInputStyle.voice) {
      state.style = ImInputStyle.voice;
      state.focusNode.unfocus();
    } else {
      state.style = ImInputStyle.text;
      if (state.focusNode.canRequestFocus) {
        state.focusNode.requestFocus();
      }
    }
    update();
    imCtrl.scrollToEnd();
  }

  void actionEmoji() {
    if (state.style != ImInputStyle.emoji) {
      state.style = ImInputStyle.emoji;
      state.focusNode.unfocus();
    } else {
      state.style = ImInputStyle.text;
      if (state.focusNode.canRequestFocus) {
        reCallKeyboard();
      }
    }
    update();
    imCtrl.scrollToEnd();
  }

  void actionAdd() {
    if (state.style != ImInputStyle.add) {
      state.style = ImInputStyle.add;
      state.focusNode.unfocus();
    } else {
      state.style = ImInputStyle.text;
      if (state.focusNode.canRequestFocus) {
        reCallKeyboard();
      }
    }
    update();
    imCtrl.scrollToEnd();
  }

  void getEmoji(String name, String item) {
    var selection = state.textCtrl.selection;
    var start = max(selection.start, 0);
    var end = max(selection.end, 0);
    state.status = ImInputStatus.inputing;
    state.textCtrl.text = state.textCtrl.text.replaceRange(start, end, name);
    update(['input']);
  }

  void actionSend() {
    state.status = ImInputStatus.edit;
    imCtrl.sendEvent(state.textCtrl.text);
    state.textCtrl.clear();

    update();
  }

  void actionSendVoice(int sections) {
    state.status = ImInputStatus.edit;
    imCtrl.sendVoiceEvent(sections);

    update();
  }

  void actionSendPicture({
    required String path,
    double? width,
    double? height,
  }) {
    state.status = ImInputStatus.edit;
    imCtrl.sendPictureEvent(
      path: path,
      width: width,
      height: height,
    );
    update();
  }

  void actionSendLocation({
    required String path,
    double? width,
    double? height,
  }) {
    state.status = ImInputStatus.edit;
    imCtrl.sendPictureEvent(
      path: path,
      width: width,
      height: height,
    );
    update();
  }

  void actionSendCard({
    required String path,
    double? width,
    double? height,
  }) {
    state.status = ImInputStatus.edit;
    imCtrl.sendCardEvent(
      path: path,
    );
    update();
  }

  void reCallKeyboard() {
    state.focusNode.unfocus();
    Future.delayed(const Duration(milliseconds: 100)).then((value) {
      state.focusNode.requestFocus();
    });
  }

  /// 在 onInit() 之后调用 1 帧。这是进入的理想场所
  @override
  void onReady() {
    super.onReady();
  }

  /// 在 [onDelete] 方法之前调用。
  @override
  void onClose() {
    super.onClose();
    state.dispose();
  }

  /// dispose 释放内存
  @override
  void dispose() {
    super.dispose();
  }
}
